package com.chancein.cloud.report.charts.service.template;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.chancein.cloud.ocr.process.domain.OcrExcelData;
import com.chancein.cloud.report.charts.domain.ChartJson;
import com.chancein.cloud.report.charts.domain.OcrProcessReqDto;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;

import java.io.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static com.chancein.cloud.report.charts.common.constant.CommonConstant.*;
import static com.chancein.cloud.report.charts.common.constant.OcrDataConstant.*;
import static com.chancein.cloud.report.charts.common.constant.HttpConstant.*;
import static com.chancein.cloud.report.charts.common.constant.EsConstant.*;
import static com.chancein.cloud.report.charts.config.InitParamConfig.*;
import static com.chancein.cloud.report.charts.service.ReportChartsService.ocrProcessApiService;

/**
 * 修复原有数据模板
 *
 * @author: LiaoZiHao
 * @date: 2023/8/3 11:42
 * Copyright © 2022 Hundsun Technologies Inc. All Rights Reserved
 */
@Slf4j
public class RepairDataTemplate {
    /**
     * 修复原有数据
     *
     * @date 2023/8/4 14:20
     * @author liaozihao
     * @param sourceFilename 源含有部分错误文件
     * @param targetFilename 目标无错误文件
     */
    public static void repairExportData(String sourceFilename, String targetFilename) {
        log.info(sourceFilename + " 修复[开始]...修复后数据在 " + targetFilename + " 文件中");
        String sourceFullPath = FILE_SAVE_PATH + File.separator + sourceFilename;
        String targetFullPath = FILE_SAVE_PATH + File.separator + targetFilename;
        File sourceFile = new File(sourceFullPath);
        File targetFile = new File(targetFullPath);
        BufferedReader reader;
        BufferedWriter writer;
        // 存储进度
        int lineNum = 0;
        int errorNum = 0;
        try {
            reader = new BufferedReader(new FileReader(sourceFile));
            writer = new BufferedWriter(new FileWriter(targetFile, true));
            String line;
            while ((line = reader.readLine()) != null) {
                lineNum++;
                JSONObject ocrJson = JSON.parseObject(line);
                String ocrParseData = ocrJson.getString(OCR_PARSE_DATA);
                if (isErrorMes(ocrParseData)) {
                    errorNum++;
                    // 是错误的数据，重新发起请求
                    String id = ocrJson.getString(OCR_PARSE_DATA_ID);
                    // 拿出 ID 封装一个请求，重新发起 OCR 识别请求
                    OcrProcessReqDto ocrProcessReqDto = buildOcrReqById(id);
                    if (ObjectUtil.isEmpty(ocrProcessReqDto)) {
                        log.error("[ES]封装一个请求失败; 错误数据[id=" + id + "]");
                        ocrParseData = OCR_RSP_UN_RESOLVE;
                    } else {
                        OcrExcelData ocrExcelData = ocrProcessApiService.getExcel(ocrProcessReqDto);
                        ocrParseData = (ocrExcelData != null) ? JSONObject.toJSONString(ocrExcelData) : OCR_RSP_UN_RESOLVE;
                    }
                    ocrJson.put(OCR_PARSE_DATA, ocrParseData);
                    writer.write(ocrJson.toString());
                    writer.newLine();
                } else {
                    writer.write(line);
                    writer.newLine();
                }
                if (lineNum % 1000 == 0) {
                    log.info("修复已完成[" + lineNum + "]条数据, error数据共[" + errorNum + "]条");
                }
            }
            writer.close();
            reader.close();
        } catch (IOException e) {
            log.error("[RepairData] sourceFile 打开失败或 targetFile 创建失败...");
            e.printStackTrace();
        }
    }
    /**
     * 返回一个根据ID查询的一条请求
     *      根据ID查询，
     *
     * @date 2023/8/4 14:45
     * @author liaozihao
     * @param id 图表ID
     * @return {@link OcrProcessReqDto}
     */
    public static OcrProcessReqDto buildOcrReqById(String id) throws IOException {
        // 1. 封装一个es请求
        SearchRequest searchRequest = new SearchRequest(ES_INDEX_NAME);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        TermQueryBuilder idQueryBuilder = QueryBuilders.termQuery("_id", id);
        searchSourceBuilder.query(idQueryBuilder);
        searchRequest.source(searchSourceBuilder);
        // 2. 发起请求
        SearchResponse response = client.search(searchRequest);
        // 3. 解析结果并封装一个 OcrReq
        SearchHits searchHits = response.getHits();
        SearchHit[] hits = searchHits.getHits();
        OcrProcessReqDto ocrProcessReqDto = new OcrProcessReqDto();
        if (hits.length > 0) {
            JSONObject reportChartsJsonData = JSONObject.parseObject(hits[0].getSourceAsString());

            ocrProcessReqDto.setOrigin(ServerUrl);
            String uri = reportChartsJsonData.getString(OCR_REQ_FILEPATH);
            if (uri.charAt(0) != '/') {
                uri = "/" + uri;
                uri = OCR_REP_URI_PREFIX + reportChartsJsonData.getString(OCR_REQ_PUB_DATE).replace("-", "/") + uri;
            }
            ocrProcessReqDto.setUri(uri);
            ocrProcessReqDto.setVectorgraphText(reportChartsJsonData.getString(OCR_REQ_VEC_TEXT));
            // 封装一个请求所需的 chartJson 字段
            ChartJson chartJson = new ChartJson();
            chartJson.setId(reportChartsJsonData.getString(OCR_REQ_ID));
            chartJson.setPageIndex(reportChartsJsonData.getString(OCR_REQ_PAGE_INDEX));
            chartJson.setPicRect(reportChartsJsonData.getString(OCR_REQ_PIC_RECT));
            chartJson.setPdfFilePath(reportChartsJsonData.getString(OCR_REQ_PDF_FILEPATH));
            chartJson.setIpadMarkerType(OCR_REQ_IPAD_MARKER_TYPE);
            ocrProcessReqDto.setChartJson(JSON.toJSONString(chartJson));
            ocrProcessReqDto.setTimestamp(OCR_REQ_TIMESTAMP);
        }
        // 4. 返回结果
        return ocrProcessReqDto;
    }
    /**
     *  判断 ocrParseData 是否是错误的数据
     *      使用正则表达式识别 ocrParseData 中的错误数据
     *
     * @date 2023/8/4 16:01
     * @author liaozihao
     * @param ocrParseData ocr 解析数据
     * @return {@link Boolean}
     */
    public static Boolean isErrorMes(String ocrParseData) {
        if (StrUtil.equals(ocrParseData, HTTP_BLANK_FILE_ERROR)) {
            return Boolean.TRUE;
        }
        // 使用正则表达式提取 "[message]"
        String pattern = "\\[HTTP_([A-Z_]+)\\s(\\d+)]";
        Pattern regex = Pattern.compile(pattern);
        Matcher matcher = regex.matcher(ocrParseData);

        if (matcher.find()) {
            String errorMes = matcher.group(0);
            if (StrUtil.equals(errorMes, HTTP_504_FILE_ERROR) ||
                StrUtil.equals(errorMes, HTTP_401_FILE_ERROR) ||
                StrUtil.equals(errorMes, HTTP_500_FILE_ERROR)) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }
}
